package com.zmj.comm;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zmj.anno.MyAjax;
import com.zmj.anno.RequestPath;
import com.zmj.constant.CommConstant;
import com.zmj.utils.PackageUtil;
//当值为0或者大于0时，表示容器在应用启动时就加载这个servlet；
//当是一个负数时或者没有指定时，则指示容器在该servlet被选择时才加载。
//正数的值越小，启动该servlet的优先级越高。
@WebServlet(value = CommConstant.XM_ROOT, loadOnStartup = CommConstant.ONE)
public class DispatcherServlet extends HttpServlet{
  static Map<String, String> config=new HashMap<String, String>();
  static String packagePath;
  static {
	  InputStream in=DispatcherServlet.class.getClassLoader().getResourceAsStream(CommConstant.PUB_CONFIG);
	  Properties pt=new Properties();
	  try {
		pt.load(in);
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	  packagePath=pt.getProperty(CommConstant.PACKAGE_PATH);
	  
  }
	@Override
public void init() throws ServletException {
	try {
		//通过完整包名拿到所有的类
		List<String> list=PackageUtil.getClassName(packagePath);
		
		for (String cpatch : list) {
			//遍历类名获取字节码
			Class cls=Class.forName(cpatch);
			//拿到指定包中的所有方法
			Method[] methods=cls.getMethods();
			
			for (Method m:methods) {
				//遍历所有方法拿到注解
				
				RequestPath pt =m.getAnnotation(RequestPath.class);
				
				if (null!=pt) {
					//key 为注解写的内容  value为   类名#方法名
					config.put(pt.value(), cls.getName()+CommConstant.JINHAO+m.getName());
				}
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//通过我们输入的网址取出后面的路径（要与我们写的注解一样）
		String key = req.getServletPath();
		//因为我们每个注解对应一个方法，利用mapper存着，获取方法名（准备用反射获取字节码执行此方法）
		//所以Controller中的servlet是假的。这个程序只有一个Servlet：DisPatherServlet
		String path=config.get(key);
		
		String[] sp = path.split("#");
		String className = sp[0]; //我们的类全名
		String methodName = sp[1]; //我们的方法名
		try {
			Class cls=Class.forName(className);
			//实例化，不然无法调用。获取这个类的一个对象
			Object object=cls.newInstance();
			
			
			//根据方法名称获取方法;执行目标方法,得到返回值
			Method method = cls.getMethod(methodName, HttpServletRequest.class);
			String result = method.invoke(object, req).toString();
			
			//获取MyAjax注解
			MyAjax mj = method.getAnnotation(MyAjax.class);
			
			
			if(null != mj){
				resp.getWriter().print(result);
			}else{//代表页面跳转的请求
				
				if(result.contains(":")){
					resp.sendRedirect(result.substring(result.indexOf(":")+1)); //请求重发
				}else{
					req.getRequestDispatcher(result).forward(req, resp);//请求转发
				}
				
			}
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
